package hr.ctg.service;

import hr.ctg.domain.action.GuidesActionBean;
import hr.ctg.domain.model.Mjesto;
import hr.ctg.domain.model.Otok;
import hr.ctg.domain.model.Park;
import hr.ctg.service.dao.DrzavaDAO;
import hr.ctg.service.dao.MjestoDAO;
import hr.ctg.service.dao.OtokDAO;
import hr.ctg.service.dao.ParkDAO;
import hr.ctg.util.StringUtil;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;

import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.Factory;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.web.RequestParameter;
import org.jboss.seam.cache.CacheProvider;
import org.jboss.seam.log.Log;
import org.xml.sax.SAXException;

import com.aetrion.flickr.FlickrException;
import com.aetrion.flickr.REST;
import com.aetrion.flickr.photos.Photo;
import com.aetrion.flickr.photos.PhotoList;
import com.aetrion.flickr.photos.PhotosInterface;
import com.aetrion.flickr.photos.SearchParameters;

@AutoCreate
@Name("flickrService")
public class FlickrService {
	private static final int RESULTS_PER_PAGE = 50;
	private static final int PAGE = 0;

	@Logger
	Log log;
	@In
	CacheProvider cacheProvider;
	@In
	MjestoDAO mjestoDAO;
	@In
	OtokDAO otokDAO;
	@In
	ParkDAO parkDAO;
	@In
	DrzavaDAO drzavaDAO;
	@In(create = true)
	GuidesActionBean guides;

	@RequestParameter
	Integer idMjesta;
	@RequestParameter
	Integer idOtoka;
	@RequestParameter
	Integer idParka;

	private PhotosInterface photosInterface;

	@Create
	public void init() {
		REST rest;
		try {
			rest = new REST();
			photosInterface = new PhotosInterface(
					"743b4187c8fa3e96da93c230d32ddb61", "fa1f68832eaa8dbd",
					rest);
		} catch (final ParserConfigurationException e) {
			log.error(e.getMessage(), e);
		}

	}

	@SuppressWarnings("unchecked")
	public List<Photo> getPhotos(final String minLongitude,
			final String minLatitude, final String maxLongitude,
			final String maxLatitude, final int accuracy, final String text,
			final int resultsPerPage, final int page) {
		final SearchParameters parameters = new SearchParameters();
		String key = null;
		if (text != null) {
			parameters.setText(text);
			key = text;
		}
		if (minLongitude != null) {
			parameters.setBBox(minLongitude, minLatitude, maxLongitude,
					maxLatitude);
			parameters.setText(StringUtil.clearForUrl(text));
			parameters.setAccuracy(accuracy);
			key = minLongitude + minLatitude + maxLongitude + maxLatitude;
		}
		List<Photo> photos;
		try {
			List<Photo> cache = (List) cacheProvider.get("flickr", key);
			if (cache == null) {
				photos = new ArrayList<Photo>();
				final PhotoList photoList = photosInterface.search(parameters,
						resultsPerPage, page);
				for (final Object object : photoList) {
					final Photo photo = (Photo) object;
					if (photo.isPublicFlag()) {
						photos.add(photo);
					}
				}
				cacheProvider.put("flickr", key, photos);
			} else {
				photos = cache;
			}
			return photos;
		} catch (final IOException e) {
			log.error(e.getMessage(), e);
		} catch (final SAXException e) {
			log.error(e.getMessage(), e);
		} catch (final FlickrException e) {
			log.error(e.getMessage(), e);
		}
		return Collections.EMPTY_LIST;
	}

	public List<Photo> getPhotos(final String minLongitude,
			final String minLatitude, final String maxLongitude,
			final String maxLatitude, final int accuracy, final String text) {
		return getPhotos(minLongitude, minLatitude, maxLongitude, maxLatitude,
				accuracy, text, RESULTS_PER_PAGE, PAGE);
	}

	public List<Photo> getPhotos(final String text) {
		return getPhotos(null, null, null, null, 0, text, RESULTS_PER_PAGE,
				PAGE);
	}

	@SuppressWarnings("unchecked")
	@Factory(value = "flickrSlikeByMjesto")
	public List<Photo> getPhotosByMjesto() {
		if (idMjesta == null) {
			return Collections.EMPTY_LIST;
		}
		Mjesto m = mjestoDAO.find(idMjesta);
		if (m.getLongituda() == null) {
			return Collections.EMPTY_LIST;
		}
		return getPhotosByMjesto(m);
	}

	public List<Photo> getPhotosByMjesto(Mjesto m) {
		final String minLongitude = Double.toString(m.getLongituda() - 0.05);
		final String minLatitude = Double.toString(m.getLatituda() - 0.05);
		final String maxLongitude = Double.toString(m.getLongituda() + 0.05);
		final String maxLatitude = Double.toString(m.getLatituda() + 0.05);
		return getPhotos(minLongitude, minLatitude, maxLongitude, maxLatitude,
				11, m.getNaziv());
	}

	@SuppressWarnings("unchecked")
	@Factory(value = "flickrSlikeByOtok")
	public List<Photo> getPhotosByOtok() {
		if (idOtoka == null) {
			return Collections.EMPTY_LIST;
		}
		Otok o = otokDAO.find(idOtoka);
		if (o.getLongituda() == null) {
			return Collections.EMPTY_LIST;
		}
		final String minLongitude = Double.toString(o.getLongituda() - 0.25);
		final String minLatitude = Double.toString(o.getLatituda() - 0.07);
		final String maxLongitude = Double.toString(o.getLongituda() + 0.25);
		final String maxLatitude = Double.toString(o.getLatituda() + 0.07);
		return getPhotos(minLongitude, minLatitude, maxLongitude, maxLatitude,
				6, o.getNaziv());
	}

	@SuppressWarnings("unchecked")
	@Factory(value = "flickrSlikeByPark")
	public List<Photo> getPhotosByPark() {
		Park p = parkDAO.find(idParka);
		if (p.getLongituda() == null) {
			return Collections.EMPTY_LIST;
		}
		final String minLongitude = Double.toString(p.getLongituda() - 0.05);
		final String minLatitude = Double.toString(p.getLatituda() - 0.05);
		final String maxLongitude = Double.toString(p.getLongituda() + 0.05);
		final String maxLatitude = Double.toString(p.getLatituda() + 0.05);
		return getPhotos(minLongitude, minLatitude, maxLongitude, maxLatitude,
				11, p.getNaziv());
	}

	@SuppressWarnings("unchecked")
	@Factory("flickrSlikeByDrzava")
	public List<Photo> getPhotosByDrzava() {
		List<Mjesto> mjestoList = guides.getTopMjesta(100);
		Mjesto m = mjestoList.get((int) (Math.random() * mjestoList.size()));
		if (m.getLongituda() == null) {
			return Collections.EMPTY_LIST;
		}
		return getPhotosByMjesto(m);
	}
}
